package com.heima.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

/**
 * @Author: Ethan Yankang
 * @Program: 面试必会代码
 * @Date: 2024-08-31 11:05
 **/
/*
 * @description 通过反射获取所有类型的构造方法
 *
 * 重要方法:
 *
 * 构造函数方法
 * 1).批量的方法：
 *          public Constructor[] getConstructors()：所有"公有的"构造方法
            public Constructor[] getDeclaredConstructors()：获取所有的构造方法(包括私有、受保护、默认、公有)
 *
 *
 * 2).获取单个的方法，并调用：
 *          public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法：
 * 			public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"可以是私有的，或受保护、默认、公有；
 *
 *
 * 3).调用构造方法：
 * 			Constructor.newInstance(Object... initargs)
 *
 *
 * ========================================================================================================================
 *
 * 获取成员变量
 * 1).批量的
 * 		1).Field[] getFields():获取所有的"公有字段"
 * 		2).Field[] getDeclaredFields():获取所有字段，包括：私有、受保护、默认、公有；
 *
 * 2).获取单个的：
 * 		1).public Field getField(String fieldName):获取某个"公有的"字段；
 * 		2).public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)
 *
 * 3).设置字段的值：
 * 		Field --> public void set(Object obj,Object value):
 * 					参数说明：
 * 					1.obj:要设置的字段所在的对象；
 * 					2.value:要为字段设置的值；
 *
 *
 * @params
 * @return
 */

public class Reflect {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//        加载Class类对象
        Class clazz = Class.forName("com.heima.reflect.Student");
//        获取所有共有构造方法
        System.out.println("**********************所有公有构造方法*********************************");
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
//       获取所有的构造方法，报货私有、公有、受保护、默认等
        System.out.println("************所有的构造方法(包括：私有、受保护、默认、公有)***************");
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

//        获取公有无参构造方法

        System.out.println("*****************获取公有、无参的构造方法*******************************");
        Constructor constructorNull = clazz.getConstructor(null);
        System.out.println("constructorNull = " + constructorNull);

//        调用无参构造方法
        Object obj = constructorNull.newInstance();


//        获取私有构造方法并调用
        System.out.println("******************获取私有构造方法，并调用*******************************");
        Constructor constructorsPrivate = clazz.getDeclaredConstructor(int.class);
        System.out.println("constructorsPrivate = " + constructorsPrivate);

//        暴力访问私有方法
        constructorsPrivate.setAccessible(true);
        constructorsPrivate.newInstance(18);

//        获取所有公共字段
        System.out.println("************获取所有公有的字段********************");
        Field[] field = clazz.getFields();
        for (Field field1 : field) {
            System.out.println(field1);
        }

//    获取所有的字段(包括私有、受保护、默认

        System.out.println("************获取所有的字段(包括私有、受保护、默认的)********************");
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }

//        获取公有字段并调用

        System.out.println("*************获取公有字段**并调用***********************************");
        Field name = clazz.getField("name");
        System.out.println("name = " + name);

//        为属性赋值创建了一个对象实例
        Student obj1 = (Student) clazz.getConstructor().newInstance();

        name.set(obj1,"Ethan Yankang");
//       验证是否设置成功
        System.out.println("Name="+obj1.name);


 //        获取私有字段并调用
        System.out.println("**************获取私有字段****并调用********************************");
        Field age=clazz.getDeclaredField("age");
        age.setAccessible(true);
        System.out.println("age = " + age);
        age.set(obj1,19);
//        验证年龄
        System.out.println("age= "+obj1.getAge());//注意这里的私有字段需要通过访问器来访问，就算上面开启了权限
    }
}
